home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 138 / 138.xpi / components / stumbleuponService.js
Text File  |  2010-02-03  |  20KB  |  886 lines

  1. // component defined in this file
  2. const su_EXTENSION_ID="{AE93811A-5C9A-4d34-8462-F7B864FC4696}";
  3. const su_SERVICE_NAME="StumbleUpon Service";
  4. const su_SERVICE_ID="{b97c288d-917d-4d26-bd24-3adf14f5aea3}";
  5. const su_SERVICE_CTRID = "@stumbleupon.com/stumbleupon-service;1";
  6.  
  7. const su_SERVICE_CID = Components.ID(su_SERVICE_ID);
  8.  
  9. //const SERVICE_CATS = ["app-startup"];
  10.  
  11. // Factory object
  12. var su_SERVICE_FACTORY = {
  13.     _instance: null,
  14.     
  15.     createInstance: function (outer, iid)
  16.     {
  17.         if (outer != null)
  18.             throw Components.results.NS_ERROR_NO_AGGREGATION;
  19.         
  20.         if (! (iid.equals(Components.interfaces.nsISupports) ||
  21.                 iid.equals(Components.interfaces.nsISupportsWeakReference)))
  22.             throw Components.results.NS_ERROR_INVALID_ARG;
  23.         
  24.         if (! this._instance)
  25.             this._instance = new su_Service();
  26.         
  27.         return this._instance;
  28.   }
  29. };
  30.  
  31. var su_Module = {
  32.   _registered: false,
  33.     
  34.     registerSelf: function(componentManager, fileSpec, location, type)
  35.     {
  36.         if (this._registered)
  37.             return;
  38.     
  39.         var registrar = componentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  40.         
  41.         registrar.registerFactoryLocation(
  42.                 su_SERVICE_CID,
  43.                 su_SERVICE_NAME,
  44.                 su_SERVICE_CTRID,
  45.                 fileSpec,
  46.                 location,
  47.                 type);
  48.  
  49. //        const categoryManager = Components.classes['@mozilla.org/categorymanager;1']
  50. //                .getService(Components.interfaces.nsICategoryManager);
  51. //        
  52. //        var i;
  53. //        for (i = 0; i < SERVICE_CATS.length; i++)
  54. //        {
  55. //            categoryManager.addCategoryEntry(
  56. //                    SERVICE_CATS[i],
  57. //                    su_SERVICE_CTRID,
  58. //                    su_SERVICE_CTRID,
  59. //                    true,
  60. //                    true);
  61. //        }
  62.  
  63.         this._registered = true;
  64.   },
  65.   
  66.     unregisterSelf: function(componentManager, fileSpec, location)
  67.     {
  68.     var registrar = componentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  69.         
  70.         registrar.unregisterFactoryLocation(su_SERVICE_CID, fileSpec);
  71.   },
  72.  
  73.     getClassObject: function (compMgr, cid, iid)
  74.     {
  75.         if (cid.equals(su_SERVICE_CID))
  76.             return su_SERVICE_FACTORY;
  77.         
  78.         if (!iid.equals(Components.interfaces.nsIFactory))
  79.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  80.         
  81.         throw Components.results.NS_ERROR_NO_INTERFACE;
  82.     },
  83.     
  84.     canUnload: function(componentManager)
  85.     {
  86.         return true;
  87.     }
  88. }
  89. function NSGetModule(componentManager, fileSpec)
  90. {
  91.   return su_Module;
  92. }
  93.  
  94. var su_Service = function ()
  95. {
  96.     this._hostSpec = null;
  97.     this._datastore = null;
  98.     this._stumbleReporter = null;
  99.     this._tldService = null;
  100.     this._globals = {}; // same as this._datastore.globals
  101.     this._globals.batched_error_log = "";
  102.     this._globals.batched_pref_error_log = "";
  103.     this._startupTimeMs = (new Date()).getTime();
  104.     this._batchingLog = false;
  105.     this._blockedLogErrorPending = false;
  106.     this._messageCount = 0;
  107.     this._messageLog = "";
  108.     this._messageLogEnabled = false;
  109.     this._agentDesc = "";
  110.     this._refs = [];
  111.     this._logCommunicationEnabled = false;
  112.     this._forceCampusDistEnabled = false;
  113.     this._logErrorDomain = "stumbleupon.com";
  114.     this._persistLCFD = false;
  115. }
  116. su_Service.prototype = 
  117. {
  118.     QueryInterface: function (iid)
  119.     {
  120.         if (iid.equals(Components.interfaces.nsISupports) ||
  121.                 iid.equals(Components.interfaces.nsISupportsWeakReference))
  122.             return this;
  123.         else
  124.             throw Components.results.NS_ERROR_NO_INTERFACE;
  125.     },
  126.  
  127.   get wrappedJSObject() {
  128.     return this;
  129.   },
  130.     
  131.     _createInstance: function (nsclass, nsinterface)
  132.     {
  133.         try {
  134.             return Components.classes[nsclass].createInstance(Components.interfaces[nsinterface]);
  135.         } catch (e) {
  136.             return null;
  137.         }
  138.     },
  139.     
  140.     _getService: function (nsclass, nsinterface)
  141.     {
  142.         try {
  143.             return Components.classes[nsclass].getService(Components.interfaces[nsinterface]);
  144.         } catch (e) {
  145.             return null;
  146.         }
  147.     },
  148.     
  149.     _loadScript: function (filename)
  150.     {
  151.         var uri = "chrome://stumbleupon/content/" + filename;
  152.         try {
  153.             this._getService(
  154.                         "@mozilla.org/moz/jssubscript-loader;1",
  155.                         "mozIJSSubScriptLoader")
  156.                         .loadSubScript(uri);
  157.         }
  158.         catch (e) {
  159.             this.logError("INCLUDE", e, uri);
  160.         }
  161.     },
  162.     
  163.     _addref: function (obj)
  164.     {
  165.         this._refs.push(obj);
  166.     },
  167.     
  168.     _release: function (obj)
  169.     {
  170.         var i;
  171.         for (i = 0; i < this._refs.length; i++)
  172.         {
  173.             if (this._refs[i] == obj)
  174.             {
  175.                 this._refs.splice(i, 1);
  176.                 return;
  177.             }
  178.         }
  179.     },
  180.     
  181.     _setTimeout: function ()
  182.     {
  183.         var timer = this._createInstance(
  184.                         "@mozilla.org/timer;1",
  185.                         "nsITimer");
  186.         
  187.         this._addref(timer);
  188.         var i;
  189.         var args = [];
  190.         for (i = 2; i < arguments.length; i++)
  191.             args.push(arguments[i]);
  192.  
  193.         var this_ = this;
  194.         var fn = arguments[0];
  195.         timer.initWithCallback(
  196.                 {
  197.                     QueryInterface: function (iid) {
  198.                         if (iid.equals(Components.interfaces.nsISupports) ||
  199.                                 iid.equals(Components.interfaces.nsITimerCallback))
  200.                             return this;
  201.                         else
  202.                             throw Components.results.NS_ERROR_NO_INTERFACE;
  203.                     },    
  204.                     notify: function (timer) {
  205.                         this_._release(timer);
  206.                         fn.apply(fn, args);
  207.                     }
  208.                 },
  209.                 arguments[1],
  210.                 timer.TYPE_ONE_SHOT);
  211.         return timer;
  212.     },
  213.     
  214.     _clearTimeout: function (timer)
  215.     {
  216.         timer.cancel();
  217.         this._release(timer);
  218.     },
  219.  
  220.     _setInterval: function ()
  221.     {
  222.         var timer = this._createInstance(
  223.                         "@mozilla.org/timer;1",
  224.                         "nsITimer");
  225.         
  226.         this._addref(timer);
  227.         var i;
  228.         var args = [];
  229.         for (i = 2; i < arguments.length; i++)
  230.             args.push(arguments[i]);
  231.  
  232.         var this_ = this;
  233.         var fn = arguments[0];
  234.         timer.initWithCallback(
  235.                 {
  236.                     QueryInterface: function (iid) {
  237.                         if (iid.equals(Components.interfaces.nsISupports) ||
  238.                                 iid.equals(Components.interfaces.nsITimerCallback))
  239.                             return this;
  240.                         else
  241.                             throw Components.results.NS_ERROR_NO_INTERFACE;
  242.                     },    
  243.                     notify: function (timer) {
  244.                         this_._release(timer);
  245.                         fn.apply(fn, args);
  246.                     }
  247.                 },
  248.                 arguments[1],
  249.                 timer.TYPE_REPEATING_SLACK);
  250.         return timer;
  251.     },
  252.     
  253.     _clearInterval: function (timer)
  254.     {
  255.         timer.cancel();
  256.         this._release(timer);
  257.     },
  258.  
  259.     getErrorObjectDump: function (o)
  260.     {
  261.         if (! o)
  262.             return "\n" + (typeof o);
  263.         
  264.         var str = "\n===== dump ===\n"; 
  265.         var p;
  266.         for (p in o)
  267.         {
  268.             if (p.match(/.*_ERR$/))
  269.                 continue;
  270.             
  271.             try {
  272.                 str += "[" + p + "]\n" + o[p] + "\n";
  273.             }
  274.             catch (e) {
  275.                 str += "[" + p + "] ERROR\n" + e + "\n";
  276.             }
  277.         }
  278.         str += "========";
  279.         return str;
  280.     },
  281.     
  282.     getSessionTimeMs: function ()
  283.     {
  284.         return (new Date()).getTime() - this._startupTimeMs;
  285.     },
  286.     
  287.     setMessageLogEnabled: function (enabled)
  288.     {
  289.         this._messageLogEnabled = enabled;
  290.     },
  291.     
  292.     setLogCommunicationEnabled: function (enabled)
  293.     {
  294.         this._logCommunicationEnabled = enabled;
  295.     },
  296.     
  297.     setLogResourceCFD: function (enabled)
  298.     {
  299.         this._logResourceCFD = enabled
  300.     },
  301.     
  302.     setAgentDesc: function (desc)
  303.     {
  304.         this._agentDesc = desc;
  305.     },
  306.     
  307.     setForceCampusDistEnabled: function (enabled)
  308.     {
  309.         this._forceCampusDistEnabled = enabled;    
  310.     },
  311.     
  312.     setLogErrorDomain: function (domain)
  313.     {
  314.         this._logErrorDomain = domain;
  315.     },
  316.     
  317.     getWindow: function ()
  318.     {
  319.         var enumerator = this._getService(
  320.                 "@mozilla.org/appshell/window-mediator;1",
  321.                 "nsIWindowMediator").getEnumerator("navigator:browser");
  322.  
  323.         if (! enumerator.hasMoreElements())
  324.             return null;
  325.         
  326.         return enumerator.getNext();
  327.     },
  328.     
  329.     callWindow: function ()
  330.     {
  331.         var win = this.getWindow();
  332.         if (! win)
  333.             return null;
  334.         
  335.         var args = [];
  336.         var i;
  337.         for (i = 1; i < arguments.length; i++)
  338.             args.push(arguments[i]);
  339.         
  340.         return win[arguments[0]].apply(win, args);
  341.     },
  342.     
  343.     logError: function ()
  344.     {
  345.         var i;
  346.         var str = "";
  347.         if (arguments.length != 0)
  348.         {
  349.             str += "\n";
  350.             str += this.getSessionTimeMs() + "\n";
  351.         }
  352.         for (i = 0; i < arguments.length; i++)
  353.         {
  354.             var type = typeof(arguments[i]);
  355.             if ((i == 1) && (type != "string") && (type != "number"))
  356.                 str += this.getErrorObjectDump(arguments[i]);
  357.             
  358.             else
  359.                 str += "\n" + arguments[i];
  360.         }
  361.         
  362.         this._globals.batched_error_log += (this._globals.batched_error_log == "") ? str : ("\n" + str);
  363.     
  364.         if ((this._globals.batched_error_log == "") && (this._globals.batched_pref_error_log == ""))
  365.             return;
  366.         
  367.         // By delaying for 1000 ms, we batch sets of closely spaced errors.
  368.         if (! this._batchingLog)
  369.         {
  370.             this._batchingLog = true;
  371.             this._blockedLogErrorPending = false;
  372.             this._setTimeout(function (this_) { this_._logErrorGated(); }, 1000, this);
  373.         }
  374.         else if (this._batchingLog && 
  375.                     (! this._blockedLogErrorPending))
  376.         {
  377.             // If logging is blocked, push back the logging event. -- JW
  378.             this._blockedLogErrorPending = true;
  379.             this._setTimeout(function (this_) { this_._logErrorGated(); }, 1000, this);
  380.         }
  381.     },
  382.  
  383.     _logErrorGated: function ()
  384.     {
  385.         if ((this._globals.batched_error_log == "") && (this._globals.batched_pref_error_log == ""))
  386.         {
  387.             this._batchingLog = false;
  388.             return;
  389.         }
  390.         
  391.         var consoleService =
  392.                     Components.classes["@mozilla.org/consoleservice;1"]
  393.                     .getService(Components.interfaces.nsIConsoleService);
  394.     
  395.         if (! consoleService)
  396.             return;
  397.         
  398.         var str = "StumbleUpon error message:\n";
  399.         if (this._datastore)
  400.             str += this.getHostSpec().desc;
  401.         str += this._globals.batched_error_log;
  402.         str += this._globals.batched_pref_error_log;
  403.         consoleService.logStringMessage(str);
  404.         
  405.         if (this._messageLogEnabled)
  406.         {
  407.             this._messageCount++;
  408.             this._messageLog += "\n--- " + this._messageCount;
  409.             this._messageLog += this._globals.batched_error_log + this._globals.batched_pref_error_log;
  410.         }
  411.         
  412.         var prefService = this._getService(
  413.                     "@mozilla.org/preferences-service;1",
  414.                     "nsIPrefService");
  415.     
  416.         var prefBranch = prefService.getBranch("");
  417.     
  418.         var errorCount;
  419.         if (prefBranch.getPrefType("stumble.report_error_count") == 0)
  420.             errorCount = 0;
  421.         
  422.         else
  423.             errorCount = prefBranch.getIntPref("stumble.report_error_count");
  424.     
  425.         errorCount++;
  426.         prefBranch.setIntPref("stumble.report_error_count", errorCount);
  427.         prefService.savePrefFile(null);
  428.         
  429.         var errorCountMax;
  430.         if (prefBranch.getPrefType("stumble.report_error_count_max") == 0)
  431.             errorCountMax = 3;
  432.         
  433.         else
  434.             errorCountMax = prefBranch.getIntPref("stumble.report_error_count_max");
  435.         
  436.         if (errorCount <= errorCountMax)
  437.         {
  438.             var params = "";
  439.             params += "host=" + encodeURIComponent(this.getHostSpec().desc);
  440.             params += "&count=" + errorCount;
  441.             if (this._datastore)
  442.             {
  443.                 var userid = this._datastore._userid;
  444.                 if (userid == "")
  445.                     userid = 0;
  446.                 else
  447.                     params += "&password=" + encodeURIComponent(this._datastore.getStoredPassword());
  448.                 params += "&username=" + encodeURIComponent(userid);
  449.                 params += "&nick=" + encodeURIComponent(this._datastore.getValue("$nick"));
  450.             }
  451.             else
  452.             {
  453.                 params += "&username=0";
  454.             }
  455.             params += "&version=" + encodeURIComponent(this._agentDesc);
  456.             
  457.             var simultPref = (this._globals.batched_pref_error_log == "") ? 0 : 1;
  458.             var simultOther = (this._globals.batched_error_log == "") ? 0 : 1;
  459.             
  460.             if (this._globals.batched_error_log != "")
  461.             {
  462.                 this.postAsync(
  463.                         this._agentDesc,
  464.                         "http://www." + this._logErrorDomain + "/mozbar_error.php",
  465.                         params +
  466.                             "&pref=0" +
  467.                             "&error=" + encodeURIComponent(this._globals.batched_error_log) + 
  468.                             "&simultpref=" + simultPref,
  469.                         null,
  470.                         null,
  471.                         null);
  472.             }
  473.             
  474.             if (this._globals.batched_pref_error_log != "")
  475.             {
  476.                 this.postAsync(
  477.                         this._agentDesc,
  478.                         "http://www." + this._logErrorDomain + "/mozbar_error.php",
  479.                         params +
  480.                             "&pref=1" +
  481.                             "&error=" + encodeURIComponent(this._globals.batched_pref_error_log) +
  482.                             "&simultother=" + simultOther,
  483.                         null,
  484.                         null,
  485.                         null);
  486.             }
  487.         }
  488.         this._globals.batched_error_log = "";
  489.         this._globals.batched_pref_error_log = "";
  490.         this._batchingLog = false;
  491.     },
  492.     
  493.     dd: function ()
  494.     {
  495.         var i;
  496.         var str = "";
  497.     
  498.         for (i = 0; i < arguments.length; i++)
  499.             str += "\n" + arguments[i];
  500.     
  501.         var consoleService = this._getService(
  502.                     "@mozilla.org/consoleservice;1",
  503.                     "nsIConsoleService");
  504.         consoleService.logStringMessage("StumbleUpon debug message: " + str);
  505.     },
  506.     
  507.     ddf: function ()
  508.     {
  509.         var i;
  510.         var str = "";
  511.     
  512.         for (i = 0; i < arguments.length; i++)
  513.             str += " >" + arguments[i];
  514.         
  515.         var ds = this.getDatastore();
  516.         ds.writeFile(
  517.                 ds.getLegacyNSIFile("stumbledd"),
  518.                 (ds.getTimestampStr() + str + "\n"),
  519.                 true);
  520.     },
  521.     
  522.     postAsync: function (useragent, uri, postdata, timeoutIntervalMs, callback, detail)
  523.     {
  524.         if (! postdata)
  525.             postdata = "";
  526.         
  527.         var x = this._createInstance(
  528.                     "@mozilla.org/xmlextras/xmlhttprequest;1",
  529.                     "nsIXMLHttpRequest");
  530.         var this_ = this;
  531.         if (callback)
  532.         {
  533.             x = x.QueryInterface(Components.interfaces.nsIDOMEventTarget);
  534.         
  535.             // This ensures that our detail property doesn't get garbage
  536.             // collected.  We release in the callback function. -- JW
  537.             this._addref(x);
  538.             
  539.             x.callback = callback;
  540.             x.addEventListener(
  541.                     "load",
  542.                     function (event) {
  543.                         this_._postAsyncDone(event); },
  544.                     false);
  545.         }
  546.         
  547.         if (detail)
  548.         {
  549.             x.detail = detail;
  550.             // This creates an ugly circular reference that we must be sure
  551.             // to remove. -- JW
  552.             x.detail._request = x;
  553.         }
  554.         
  555. //        netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
  556.         try {
  557.             x.open("POST", uri, true);
  558. //            x.setRequestHeader("User-Agent" , useragent);
  559.             x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  560.         } catch (e) { this.logError("POST ASYNC", e); }
  561.         x.aborted = false;
  562.         if (timeoutIntervalMs)
  563.         {
  564.             x.done = false;
  565.             
  566.             this._setTimeout(
  567.                     function (this_, request) { this_.abortPostAsync(request); },
  568.                     timeoutIntervalMs,
  569.                     this,
  570.                     x);
  571.         }
  572.         
  573.         if (this._logCommunicationEnabled)
  574.             this.dd("post async", uri, postdata);
  575.         
  576.         x.send(postdata);
  577.     },
  578.  
  579.     _postAsyncDone: function (event)
  580.     {
  581.         var request = event.target;
  582.         if (request.readyState != 4)
  583.             return;
  584.     
  585.         this._release(request);
  586.         if (request.detail)
  587.             delete request.detail._request;
  588.         var callback = request.callback;
  589.         callback(request);
  590.     
  591.         if (request.status == 200)
  592.             request.done = true;
  593.     },
  594.     
  595.     abortPostAsync: function (request)
  596.     {
  597.         if (request.done)
  598.             return;
  599.         
  600.         request.aborted = true;
  601.         this._release(request);
  602.     
  603.         if (request.detail)
  604.             delete request.detail._request;
  605.     
  606.         request.abort();
  607.     
  608.         if (! request.callback) return;
  609.     
  610.         var callback = request.callback;
  611.         callback(request);
  612.     },
  613.     
  614.     getHostSpec: function (optNavigatorObject)
  615.     {
  616.         if (this._hostSpec)
  617.             return this._hostSpec;
  618.         
  619.         if (! this._datastore)
  620.             this.getDatastore();
  621.         
  622.         var spec = {};
  623.         try {
  624.         
  625.         const MOZILLA   = "{86c18b42-e466-45a9-ae7a-9b95ba6f5640}";
  626.         const FIREFOX   = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
  627.         const SEAMONKEY = "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}";
  628.         const NETSCAPE  = "{3db10fab-e461-4c80-8b97-957ad5f8ea47}";
  629.         const FLOCK     = "{a463f10c-3994-11da-9945-000d60ca027b}";
  630.     
  631.         var os_str = "";
  632.         if ("@mozilla.org/xre/app-info;1" in Components.classes)
  633.         {
  634.             // running under Mozilla 1.8 or later
  635.             var appinfo = this._getService(
  636.                 "@mozilla.org/xre/app-info;1",
  637.                 "nsIXULAppInfo");
  638.             
  639.             spec.id = appinfo.ID;
  640.             spec.version = appinfo.version;
  641.             try {
  642.                 appinfo = appinfo.QueryInterface(Components.interfaces.nsIXULRuntime);
  643.                 os_str = appinfo.OS.toLowerCase();
  644.             }
  645.             catch (e) {
  646.                 os_str = navigator.userAgent.toLowerCase();
  647.             }
  648.         }
  649.         else
  650.         {
  651.             if (optNavigatorObject)
  652.                 os_str = optNavigatorObject.userAgent.toLowerCase();
  653.             else
  654.                 os_str = "win";
  655.             
  656.             try {
  657.                 spec.id = this._datastore.getValue("app.id");
  658.                 spec.version = this._datastore.getValue("app.version");
  659.             } catch(e) {
  660.             // very old version
  661.                 spec.id = MOZILLA;
  662.                 spec.version = "0.0";
  663.             }
  664.         }
  665.         spec.win = (os_str.indexOf("win") != -1);
  666.         spec.mac = ((os_str.indexOf("mac") != -1)  || 
  667.                     (os_str.indexOf("darwin") != -1));
  668.         
  669.         spec.mozilla = false;
  670.         spec.firefox = false;
  671.         spec.seamonkey = false;
  672.         spec.netscape = false;
  673.         spec.flock = false;
  674.         
  675.         spec.label = "the browser";
  676.         switch (spec.id)
  677.         {
  678.             case MOZILLA:   spec.mozilla = true;   spec.label = "Mozilla";   break;
  679.             case FIREFOX:   spec.firefox = true;   spec.label = "Firefox";   break;
  680.             case SEAMONKEY: spec.seamonkey = true; spec.label = "Seamonkey"; break;
  681.             case NETSCAPE:  spec.netscape = true;  spec.label = "Netscape";  break;
  682.             case FLOCK:     spec.flock = true;     spec.label = "Flock";     break;
  683.         }
  684.         
  685.         spec.desc = spec.label.toLowerCase();
  686.         
  687.         spec.desc += "/" + spec.version + "/[[" + os_str + "]]";
  688.         
  689.         spec.toolkit = spec.firefox || spec.flock || (spec.netscape && 
  690.                 spec.version.match(/^[89]\./));
  691.         
  692.         spec.places = (spec.firefox && Components.interfaces.nsINavBookmarksService &&
  693.                 Components.interfaces.nsITaggingService);
  694.         
  695.         spec.ff2plus = false;
  696.         
  697.         spec.ff3plus = false;
  698.         
  699.         try {
  700.             // introduced in ff 1.5
  701.             var vc = this._getService(
  702.                     "@mozilla.org/xpcom/version-comparator;1",
  703.                     "nsIVersionComparator");
  704.             
  705.             if (vc.compare(spec.version, "2.0") >= 0)
  706.                 spec.ff2plus = true;
  707.             
  708.             if (vc.compare(spec.version, "3.0") >= 0)
  709.                 spec.ff3plus = true;
  710.         } catch (e) {}
  711.         
  712.         
  713.         spec.sha1 = (Components.interfaces.nsICryptoHash) ? true : false;
  714.         
  715.     //    var file = this._getService(
  716.     //                "@mozilla.org/file/directory_service;1",
  717.     //                "nsIProperties")
  718.     //                .get("ProfD", Components.interfaces.nsIFile);
  719.     //
  720.     //    file.append("extensions");
  721.     //    file.append("{AE93811A-5C9A-4d34-8462-F7B864FC4696}");
  722.     //    
  723.     //    if (file.exists())
  724.     //        return null;
  725.         
  726.         spec.dist = null;
  727.         if (this._datastore.isPrefDefined("app.distributor.channel"))
  728.         {
  729.             var dist = "ff" + this._datastore.getValue("app.distributor.channel");
  730.             if (dist == "ffcampus")
  731.                 spec.dist = dist;
  732.         }
  733.         
  734.         if (this._forceCampusDistEnabled)
  735.             spec.dist = "ffcampus";
  736.         
  737.         }
  738.         catch (e) {
  739.             spec.desc = os_str;
  740.         }
  741.     
  742.         if (optNavigatorObject)
  743.             this._hostSpec = spec;
  744.         
  745.         return spec;
  746.     },
  747.     
  748.     getDatastore: function ()
  749.     {
  750.         if (this._datastore)
  751.             return this._datastore;
  752.         
  753.         this._loadScript("datastore.js");
  754.         
  755.         var enabledb = (Components.interfaces.nsINavBookmarksService 
  756.                 && Components.interfaces.nsITaggingService); 
  757.         
  758.         if (enabledb) 
  759.             this._loadScript("DatabaseConnection.js"); 
  760.         
  761.         this._datastore = new su_Datastore(this, enabledb);
  762.         
  763.         return this._datastore;
  764.     },
  765.     
  766.     getStumbleReporter: function ()
  767.     {
  768.         if (this._stumbleReporter)
  769.             return this._stumbleReporter;
  770.         
  771.         this._loadScript("stumbleReporter.js"); 
  772.  
  773.         this._stumbleReporter = new su_StumbleReporter(this);
  774.  
  775.         return this._stumbleReporter;
  776.     },
  777.     
  778.     getEffectiveTLD: function (url)
  779.     {
  780.         if (! url.match(/^(http:|https:|ftp:)/i))
  781.             return null;
  782.         
  783.         var spliturl = url.split("/");
  784.         if (spliturl.length < 3)
  785.             return null;
  786.         
  787.         var alt = spliturl[2].match(/([^\.]*\.homeip\.net|[^\.]*\.stumble\.net)$/);
  788.         if (alt)
  789.             return alt[1];
  790.         
  791.         if (! this._tldService)
  792.         {
  793.             if (Components.interfaces.nsIEffectiveTLDService)
  794.             {
  795.                 this._tldService = this._getService(
  796.                         "@mozilla.org/network/effective-tld-service;1",
  797.                         "nsIEffectiveTLDService");
  798.             }
  799.             else
  800.             {
  801.                 this._loadScript("tldEmulation.js");
  802.                 this._tldService = su_EmulatedTLDService;
  803.             }
  804.         }
  805.         
  806.         var out = null;
  807.         
  808.         try {
  809.             out = this._tldService.getBaseDomainFromHost(spliturl[2], 0);
  810.         } catch (e) {}
  811.         return out;
  812.     },
  813.     
  814.     getSha1: function (str) 
  815.     {
  816.         var engine;
  817.         try {
  818.             engine = this._createInstance(
  819.                         "@mozilla.org/security/hash;1",
  820.                         "nsICryptoHash");
  821.             
  822.             if (! engine)
  823.                 return null;
  824.             
  825.             engine.init(engine.SHA1);
  826.             var charcodes = new Array();
  827.             for (var i = 0; i < str.length; i++)
  828.                 charcodes.push(str.charCodeAt(i));
  829.         
  830.             engine.update(charcodes, str.length);
  831.             return engine.finish(true);
  832.         }
  833.         catch (e) {
  834.             return null;
  835.         }
  836.     }
  837. };
  838.  
  839. function su_dd()
  840. {
  841.     var service;
  842.     try {
  843.         service = Components.classes["@stumbleupon.com/stumbleupon-service;1"].getService().wrappedJSObject;
  844.     }
  845.     catch (e) {
  846.         service = su_service;
  847.     }
  848.     
  849.     service.dd.apply(service, arguments);
  850. }
  851.  
  852. var su_log = su_dd;
  853.  
  854. function su_ddf()
  855. {
  856.     var service;
  857.     try {
  858.         service = Components.classes["@stumbleupon.com/stumbleupon-service;1"].getService().wrappedJSObject;
  859.     }
  860.     catch (e) {
  861.         service = su_service;
  862.     }
  863.     
  864.     service.ddf.apply(service, arguments);
  865. }
  866.  
  867. var su_logf = su_ddf;
  868.  
  869. function su_dump_object(o)
  870. {
  871.     var str = "";
  872.     var p;
  873.     
  874.     for (p in o)
  875.     {
  876.         try {
  877.             str += "[" + p + "]\n" + o[p] + "\n\n";
  878.         }
  879.         catch (e) {
  880.             str += "[" + p + "] ERROR\n" + e + "\n\n";
  881.         }
  882.     }
  883.     
  884.     su_dd(str);
  885. }
  886.